From 8cfa8e2fbe4c9a1200ba7307a416afcb6fbf79ce Mon Sep 17 00:00:00 2001 From: "kaf24@firebug.cl.cam.ac.uk" Date: Mon, 14 Nov 2005 15:21:16 +0100 Subject: [PATCH] Failure to revalidate a writable pagetable page should crash the offending domain, not merely pause it. Also, callers can now specify another domain to domain_crash(). Signed-off-by: Keir Fraser --- xen/arch/x86/domain.c | 2 +- xen/arch/x86/mm.c | 11 ++++------- xen/arch/x86/shadow_public.c | 4 ++-- xen/arch/x86/vmx.c | 8 ++++---- xen/arch/x86/vmx_vmcs.c | 10 +++++----- xen/common/domain.c | 26 +++++++++++++++++--------- xen/common/schedule.c | 2 +- xen/include/asm-ia64/vmx_vpd.h | 2 +- xen/include/xen/sched.h | 9 +++++---- 9 files changed, 40 insertions(+), 34 deletions(-) diff --git a/xen/arch/x86/domain.c b/xen/arch/x86/domain.c index b20a4accc8..c6a334f8d1 100644 --- a/xen/arch/x86/domain.c +++ b/xen/arch/x86/domain.c @@ -578,7 +578,7 @@ static void load_segments(struct vcpu *n) put_user(regs->rcx, rsp-11) ) { DPRINTK("Error while creating failsafe callback frame.\n"); - domain_crash(); + domain_crash(n->domain); } regs->entry_vector = TRAP_syscall; diff --git a/xen/arch/x86/mm.c b/xen/arch/x86/mm.c index 5a9e4a3cc3..a85b5fa52c 100644 --- a/xen/arch/x86/mm.c +++ b/xen/arch/x86/mm.c @@ -2529,7 +2529,7 @@ int do_update_va_mapping(unsigned long va, u64 val64, * not enough information in just a gpte to figure out how to * (re-)shadow this entry. */ - domain_crash(); + domain_crash(d); } rc = shadow_do_update_va_mapping(va, val, v); @@ -2918,7 +2918,6 @@ int revalidate_l1( { l1_pgentry_t ol1e, nl1e; int modified = 0, i; - struct vcpu *v; for ( i = 0; i < L1_PAGETABLE_ENTRIES; i++ ) { @@ -2944,7 +2943,6 @@ int revalidate_l1( if ( unlikely(!get_page_from_l1e(nl1e, d)) ) { - MEM_LOG("ptwr: Could not re-validate l1 page"); /* * Make the remaining p.t's consistent before crashing, so the * reference counts are correct. @@ -2953,9 +2951,8 @@ int revalidate_l1( (L1_PAGETABLE_ENTRIES - i) * sizeof(l1_pgentry_t)); /* Crash the offending domain. */ - set_bit(_DOMF_ctrl_pause, &d->domain_flags); - for_each_vcpu ( d, v ) - vcpu_sleep_nosync(v); + MEM_LOG("ptwr: Could not revalidate l1 page"); + domain_crash(d); break; } @@ -3348,7 +3345,7 @@ int ptwr_do_page_fault(struct domain *d, unsigned long addr, /* Toss the writable pagetable state and crash. */ unmap_domain_page(d->arch.ptwr[which].pl1e); d->arch.ptwr[which].l1va = 0; - domain_crash(); + domain_crash(d); return 0; } diff --git a/xen/arch/x86/shadow_public.c b/xen/arch/x86/shadow_public.c index 1f3240554a..b96e13e64e 100644 --- a/xen/arch/x86/shadow_public.c +++ b/xen/arch/x86/shadow_public.c @@ -239,13 +239,13 @@ static pagetable_t page_table_convert(struct domain *d) l4page = alloc_domheap_page(NULL); if (l4page == NULL) - domain_crash(); + domain_crash(d); l4 = map_domain_page(page_to_pfn(l4page)); memset(l4, 0, PAGE_SIZE); l3page = alloc_domheap_page(NULL); if (l3page == NULL) - domain_crash(); + domain_crash(d); l3 = map_domain_page(page_to_pfn(l3page)); memset(l3, 0, PAGE_SIZE); diff --git a/xen/arch/x86/vmx.c b/xen/arch/x86/vmx.c index 68fde0e939..ca29e0836e 100644 --- a/xen/arch/x86/vmx.c +++ b/xen/arch/x86/vmx.c @@ -191,12 +191,12 @@ static inline int long_mode_do_msr_read(struct cpu_user_regs *regs) case MSR_FS_BASE: if (!(VMX_LONG_GUEST(vc))) /* XXX should it be GP fault */ - domain_crash(); + domain_crash(vc->domain); __vmread(GUEST_FS_BASE, &msr_content); break; case MSR_GS_BASE: if (!(VMX_LONG_GUEST(vc))) - domain_crash(); + domain_crash(vc->domain); __vmread(GUEST_GS_BASE, &msr_content); break; case MSR_SHADOW_GS_BASE: @@ -260,7 +260,7 @@ static inline int long_mode_do_msr_write(struct cpu_user_regs *regs) case MSR_FS_BASE: case MSR_GS_BASE: if (!(VMX_LONG_GUEST(vc))) - domain_crash(); + domain_crash(vc->domain); if (!IS_CANO_ADDRESS(msr_content)){ VMX_DBG_LOG(DBG_LEVEL_1, "Not cano address of msr write\n"); vmx_inject_exception(vc, TRAP_gp_fault, 0); @@ -273,7 +273,7 @@ static inline int long_mode_do_msr_write(struct cpu_user_regs *regs) case MSR_SHADOW_GS_BASE: if (!(VMX_LONG_GUEST(vc))) - domain_crash(); + domain_crash(vc->domain); vc->arch.arch_vmx.msr_content.shadow_gs = msr_content; wrmsrl(MSR_SHADOW_GS_BASE, msr_content); break; diff --git a/xen/arch/x86/vmx_vmcs.c b/xen/arch/x86/vmx_vmcs.c index 39dd8342f2..04b5c6bc25 100644 --- a/xen/arch/x86/vmx_vmcs.c +++ b/xen/arch/x86/vmx_vmcs.c @@ -157,13 +157,13 @@ static void vmx_map_io_shared_page(struct domain *d) mpfn = get_mfn_from_pfn(E820_MAP_PAGE >> PAGE_SHIFT); if (mpfn == INVALID_MFN) { printk("Can not find E820 memory map page for VMX domain.\n"); - domain_crash(); + domain_crash(d); } p = map_domain_page(mpfn); if (p == NULL) { printk("Can not map E820 memory map page for VMX domain.\n"); - domain_crash(); + domain_crash(d); } e820_map_nr = *(p + E820_MAP_NR_OFFSET); @@ -182,7 +182,7 @@ static void vmx_map_io_shared_page(struct domain *d) printk("Can not get io request shared page" " from E820 memory map for VMX domain.\n"); unmap_domain_page(p); - domain_crash(); + domain_crash(d); } unmap_domain_page(p); @@ -190,13 +190,13 @@ static void vmx_map_io_shared_page(struct domain *d) mpfn = get_mfn_from_pfn(gpfn); if (mpfn == INVALID_MFN) { printk("Can not find io request shared page for VMX domain.\n"); - domain_crash(); + domain_crash(d); } p = map_domain_page(mpfn); if (p == NULL) { printk("Can not map io request shared page for VMX domain.\n"); - domain_crash(); + domain_crash(d); } d->arch.vmx_platform.shared_page_va = (unsigned long)p; diff --git a/xen/common/domain.c b/xen/common/domain.c index 7a50d0e74b..7398d79808 100644 --- a/xen/common/domain.c +++ b/xen/common/domain.c @@ -125,18 +125,27 @@ void domain_kill(struct domain *d) } -void domain_crash(void) +void domain_crash(struct domain *d) { - printk("Domain %d (vcpu#%d) crashed on cpu#%d:\n", - current->domain->domain_id, current->vcpu_id, smp_processor_id()); - show_registers(guest_cpu_user_regs()); - domain_shutdown(SHUTDOWN_crash); + if ( d == current->domain ) + { + printk("Domain %d (vcpu#%d) crashed on cpu#%d:\n", + d->domain_id, current->vcpu_id, smp_processor_id()); + show_registers(guest_cpu_user_regs()); + } + else + { + printk("Domain %d reported crashed by domain %d on cpu#%d:\n", + d->domain_id, current->domain->domain_id, smp_processor_id()); + } + + domain_shutdown(d, SHUTDOWN_crash); } void domain_crash_synchronous(void) { - domain_crash(); + domain_crash(current->domain); for ( ; ; ) do_softirq(); } @@ -178,10 +187,9 @@ static __init int domain_shutdown_finaliser_init(void) __initcall(domain_shutdown_finaliser_init); -void domain_shutdown(u8 reason) +void domain_shutdown(struct domain *d, u8 reason) { - struct domain *d = current->domain; - struct vcpu *v; + struct vcpu *v; if ( d->domain_id == 0 ) { diff --git a/xen/common/schedule.c b/xen/common/schedule.c index da344c77db..3c0d50bfc8 100644 --- a/xen/common/schedule.c +++ b/xen/common/schedule.c @@ -267,7 +267,7 @@ long do_sched_op(int cmd, unsigned long arg) { TRACE_3D(TRC_SCHED_SHUTDOWN, current->domain->domain_id, current->vcpu_id, arg); - domain_shutdown((u8)arg); + domain_shutdown(current->domain, (u8)arg); break; } diff --git a/xen/include/asm-ia64/vmx_vpd.h b/xen/include/asm-ia64/vmx_vpd.h index 4f0e74aaae..760cedd586 100644 --- a/xen/include/asm-ia64/vmx_vpd.h +++ b/xen/include/asm-ia64/vmx_vpd.h @@ -122,7 +122,7 @@ extern unsigned int opt_vmx_debug_level; do { \ printk("__vmx_bug at %s:%d\n", __FILE__, __LINE__); \ show_registers(regs); \ - domain_crash(); \ + domain_crash(current->domain); \ } while (0) #endif //__ASSEMBLY__ diff --git a/xen/include/xen/sched.h b/xen/include/xen/sched.h index f2270f74c0..ef7bd9190f 100644 --- a/xen/include/xen/sched.h +++ b/xen/include/xen/sched.h @@ -220,14 +220,15 @@ extern int set_info_guest(struct domain *d, dom0_setdomaininfo_t *); struct domain *find_domain_by_id(domid_t dom); extern void domain_destruct(struct domain *d); extern void domain_kill(struct domain *d); -extern void domain_shutdown(u8 reason); +extern void domain_shutdown(struct domain *d, u8 reason); extern void domain_pause_for_debugger(void); /* - * Mark current domain as crashed. This function returns: the domain is not - * synchronously descheduled from any processor. + * Mark specified domain as crashed. This function always returns, even if the + * caller is the specified domain. The domain is not synchronously descheduled + * from any processor. */ -extern void domain_crash(void); +extern void domain_crash(struct domain *d); /* * Mark current domain as crashed and synchronously deschedule from the local -- 2.30.2